package com.example;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.ServiceLoader;

/**
 * @author 26029
 * @date 2025/4/16
 * @description
 */
public class RunService {

    /**
     * 查找所有可用的服务
     * @param args
     */
    public static void main(String[] args) {
        ServiceLoader<MyService> myServices = ServiceLoader.load(MyService.class);
        for (MyService service : myServices) {
            System.out.println(service.getClass().getSimpleName() + " => " + service.greet("世界"));
        }

        MyServiceLoader<MyService> myServiceLoader = MyServiceLoader.load(MyService.class);
        for (MyService service : myServiceLoader.getProviders()) {
            System.out.println(service.getClass().getSimpleName() + " => " + service.greet("世界"));
        }
    }
}

/**
 * 自己实现ServiceLoader类
 */
class MyServiceLoader<T> {
    private final Class<T> service; // 服务接口类型

    private final List<T> providers = new ArrayList<>(); // 所有的服务

    private final ClassLoader classLoader; // 类加载器

    public static <T> MyServiceLoader<T> load(Class<T> service) {
        return new MyServiceLoader<T>(service);
    }

    private MyServiceLoader(Class<T> service) {
        this.service = service;
        this.classLoader = Thread.currentThread().getContextClassLoader();
        doLoad();
    }

    private void doLoad() {
        try {
            // 找到所有位置的接口服务提供
            Enumeration<URL> urls = classLoader.getResources("META-INF/services/" + service.getName());
            while (urls.hasMoreElements()) {
                // 取出当前文件
                URL url = urls.nextElement();
                System.out.println("File = " + url.getPath());
                // 建立链接
                URLConnection urlConnection = url.openConnection();
                urlConnection.setUseCaches(false);
                // 读取文件输入流
                InputStream inputStream = urlConnection.getInputStream();
                // 从文件输入流获取缓存
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                // 从文件内容里面得到实现类的全类名
                String className = bufferedReader.readLine();

                while (className != null) {
                    // 通过反射拿到实现类的示例
                    Class<?> clazz = Class.forName(className, false, classLoader);
                    if (service.isAssignableFrom(clazz)) {
                        Constructor<? extends T> constructor = (Constructor<? extends T>) clazz.getConstructor();
                        T instance = constructor.newInstance();
                        providers.add(instance);
                    }
                    className = bufferedReader.readLine();
                }
            }
        } catch (Exception e) {
            System.out.println("读取异常!");
        }
    }

    // 暴露,拿到所有服务
    public List<T> getProviders() {
        return providers;
    }
}